package com.pumpkin.jschsftpdemo.util;

import ch.qos.logback.core.util.FileUtil;
import com.jcraft.jsch.*;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.sound.sampled.Port;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.Properties;
import java.util.Vector;
import java.util.function.IntPredicate;

/**
 * 上传文件到服务器
 */
@Component
public class FTPUtil {

    private static final Logger logger = LoggerFactory.getLogger(FTPUtil.class);


    private static String host;
    @Value("${ftp.host}")
    public void setHost(String host) {
        FTPUtil.host = host;
    }

    private static String user;
    @Value("${ftp.user}")
    public void seyUser(String user) {
        FTPUtil.user = user;
    }

    private static String password;
    @Value("${ftp.password}")
    public void setPassword(String password) {
        FTPUtil.password = password;
    }

    private static String basePath;
    @Value("${ftp.basePath}")
    public void setBasePath(String basePath) {
        FTPUtil.basePath = basePath;
    }

    private static Integer port;
    @Value("${ftp.port}")
    public void setPort(Integer portName) {
        port = portName;
    }


    /**
     * 上传文件到服务器
     * @param bytes
     * @param fileName
     * @throws Exception
     */
    public static void sshSftp(byte[] bytes, String fileName) throws Exception {
        Session session = null;
        Channel channel = null;

        JSch jsch = new JSch();
        if (port <= 0) {
            //连接服务器，采用默认端口
            session = jsch.getSession(user,host);
        }else {
            session = jsch.getSession(user,host,port);
        }
        //如果服务器连接不上，则抛出异常
        if (session == null) {
            throw new Exception("session is null");
        }
        //设置登录主机的密码
        session.setPassword(password);
        //设置第一次登陆的时候提示，可选值：{ask | yes | no}
        session.setConfig("StrictHostKeyChecking","no");
        //设置登录超时时间
        session.connect(30000);
        OutputStream outputStream = null;

        try {
            //建立sftp通信通道
            channel = session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;
            //进入服务器指定的文件夹
            sftp.cd(basePath);
            //列出服务器中指定的文件列表
            Vector v = sftp.ls("*");
            for (int i = 0; i < v.size(); i++) {
                System.out.println(v.get(i));
            }
            //实现从本地上传一个文件到服务器，如果要实现下载，对换一下流就可以
            outputStream = sftp.put(fileName);
            outputStream.write(bytes);
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        } finally {
            //关流操作
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }
    }

    /**
     * 从服务器下载文件
     * @param fileName
     * @param response
     * @throws Exception
     */
    public static void getFile(String fileName, HttpServletResponse response) throws Exception {
        Session session = null;
        Channel channel = null;

        JSch jsch = new JSch();
        if (port <= 0) {
            //连接服务器，采用默认端口
            session = jsch.getSession(user,host);
        }else {
            session = jsch.getSession(user,host,port);
        }
        //如果服务器连接不上，则抛出异常
        if (session == null) {
            throw new Exception("session is null");
        }
        //设置登录主机的密码
        session.setPassword(password);
        //设置第一次登陆的时候提示，可选值：{ask | yes | no}
        session.setConfig("StrictHostKeyChecking","no");
        //设置登录超时时间
        session.connect(30000);
        OutputStream outputStream = null;

        try {
            //建立sftp通信通道
            channel = session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;
            //进入服务器指定的文件夹
            sftp.cd(basePath);
            //列出服务器中指定的文件列表
            Vector v = sftp.ls("*");
            for (int i = 0; i < v.size(); i++) {
                System.out.println(v.get(i));
            }

            InputStream stream = sftp.get(fileName);

            BufferedImage bufferedImage = ImageIO.read(stream);
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            ServletOutputStream os = response.getOutputStream();
            // response.setHeader("Content-disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
            // // response.setContentType("application/octet-stream");
            response.setContentType("image/jpeg");
            // os.write(buffer);
            //实现从本地上传一个文件到服务器，如果要实现下载，对换一下流就可以
            // outputStream = sftp.put(fileName);
            // outputStream.write(bytes);
            ImageIO.write(bufferedImage, "png", os);
            // InputStream inputStream = sftp.get(fileName);


            // int len = 0;
            // byte[] buffer = new byte[inputStream.available()];
            // System.out.println("可用：" + inputStream.available());
            // inputStream.read(buffer);
            // inputStream.close();
            // System.out.println("字节：" + buffer.length);
            // ServletOutputStream os = response.getOutputStream();
            // response.setHeader("Content-disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
            // // response.setContentType("application/octet-stream");
            // response.setContentType("image/jpeg");
            // //下载
            // // sftp.get(fileName,os);
            //
            // ByteArrayOutputStream data = new ByteArrayOutputStream();
            // byte[] one = new byte[1024];
            // InputStream is = sftp.get(fileName);
            //
            // int len = -1;
            // while ((len = is.read(one)) != -1) {
            //     data.write(one, 0, len);
            //     os.write(data.toByteArray());
            // }
            // System.out.println("data的大小：" + data.size());



            // os.flush();
            // return out.toByteArray();


        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        } finally {
            //关流操作
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }
        // return null;
    }

    /**
     * 执行shell命令
     * @return
     * @throws Exception
     */
    public static StringBuffer execShellCommand() throws Exception {
        // 创建JSch对象
        JSch jSch = new JSch();
        Session jSchSession = null;
        Channel jschChannel = null;

        // 存放执行命令结果
        StringBuffer result = new StringBuffer();
        int exitStatus = 0;
        // String command = "ls -l";
        String command = "cd /home/liuning;cat banzhang.txt";

        try {
            // 根据主机账号、ip、端口获取一个Session对象
            jSchSession = jSch.getSession(user, host, port);

            // 存放主机密码
            jSchSession.setPassword(password);

            // 去掉首次连接确认
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            jSchSession.setConfig(config);

            // 超时连接时间为3秒
            jSchSession.setTimeout(3000);

            // 进行连接
            jSchSession.connect();

            jschChannel = jSchSession.openChannel("exec");
            ((ChannelExec) jschChannel).setCommand(command);

            jschChannel.setInputStream(null);
            // 错误信息输出流，用于输出错误的信息，当exitstatus<0的时候
            ((ChannelExec)jschChannel).setErrStream(System.err);

            // 执行命令，等待执行结果
            jschChannel.connect();

            // 获取命令执行结果
            InputStream in = jschChannel.getInputStream();
            /**
             * 通过channel获取信息的方式，采用官方Demo代码
             */
            byte[] tmp=new byte[1024];
            while(true){
                while(in.available() > 0){
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    result.append(new String(tmp, 0, i));
                }
                // 从channel获取全部信息之后，channel会自动关闭
                if(jschChannel.isClosed()){
                    if (in.available() > 0) {
                        continue;
                    }
                    exitStatus = jschChannel.getExitStatus();
                    break;
                }
                try{Thread.sleep(1000);}catch(Exception ee){}
            }

        } catch (Exception e) {
            logger.warn(e.getMessage());
        } finally {
            // 关闭sftpChannel
            if (jschChannel != null && jschChannel.isConnected()) {
                jschChannel.disconnect();
            }

            // 关闭jschSesson流
            if (jSchSession != null && jSchSession.isConnected()) {
                jSchSession.disconnect();
            }

        }
        logger.info("获取执行命令的结果结果："+result);
        logger.info("退出码为："+exitStatus);

        return result;
    }

}
